package presentation.web;

import presentation.UIMember;
import jaxcent.HtmlButton ;
import jaxcent.HtmlInputCheckbox ;
import jaxcent.HtmlInputPassword ;
import jaxcent.HtmlInputRadio ;
import jaxcent.HtmlInputText ;
import jaxcent.HtmlPara ;
import jaxcent.HtmlSelect ;
import jaxcent.Jaxception ;
import util.Log ;
import util.NotFoundException ;
import util.Subsystem ;
import domain.user.BadPasswordException ;
import domain.user.Privilege ;
import domain.user.UnpermittedActionException ;

/**
 * The Class EditProfilePage. Responsible for updating user profile
 *
 * @author Hadas
 */
public class EditProfilePage extends MainPage
{

	/** The change pass check box. */
	private HtmlInputCheckbox changePassCheckBox;

	/** The password text field. */
	private HtmlInputPassword pass;

	/** The new password text field. */
	private HtmlInputPassword newPass;

	/** The pass verify text field. */
	private HtmlInputPassword passVerify;

	/** The first name text field. */
	private HtmlInputText firstName;

	/** The last name text field. */
	private HtmlInputText lastName;

	/** The residence text field. */
	private HtmlInputText residence;

	/** The male gender. */
	private HtmlInputRadio maleGender;

	/** The female gender. */
	private HtmlInputRadio femaleGender;

	/** The birth day check box. */
	private HtmlInputCheckbox birthDayCheckBox;

	/** The day of birthday. */
	private HtmlSelect birthDay;

	/** The month of birthday. */
	private HtmlSelect birthMonth;

	/** The year of birthday. */
	private HtmlSelect birthYear;

	/** The errors paragraph s error messages to user. */
	private HtmlPara errorsPara;

	/**
	 * Instantiates a new Edit Profile Page.
	 *
	 */
	public EditProfilePage()
	{
		super();
		try
		{
			if (!this.verifyUserAllowedPage(Privilege.EDIT_PROFILE))
			{
				return ;
			}

			this.initHtmlComponent();
			this.setErrors();
			this.setPasswordsFields(true);
			this.makeButton();
			this.createSelectAndCheckBox();
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, null);
		}
	}

	/**
	 * Change password box handler.
	 * Determine what will happen when marking the check box
	 * If mark -> unMark
	 */
	protected void changePassBoxHandler()
	{
		try
		{
			if(this.changePassCheckBox.getChecked()){
				this.changePassCheckBox.setChecked(false);
				this.setPasswordsFields(true);
			}
			else
			{
				this.setPasswordsFields(false);
				this.changePassCheckBox.setChecked(true);
			}
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, this.changePassCheckBox);
		}
	}//End of changePassBoxHandler


	/**
	 * Check box birthday handler.
	 * Determine what will happen when marking the check box
	 * If mark -> unMark
	 */
	protected void checkBoxBirthdayHandler()
	{
		try
		{
			if(this.birthDayCheckBox.getChecked())
			{
				this.birthDayCheckBox.setChecked(false);
				this.setSelected(true);
			}
			else
			{
				this.birthDayCheckBox.setChecked(true);
				this.setSelected(false);
			}
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, this.birthDayCheckBox);
		}
	}

	/**
	 * html button handler.
	 * Handles pressing the save changes button including all corresponding domain servies
	 * like updating user profile etc.
	 */
	protected void htmlButtonHandler()
	{
		boolean passUpdatSucceed = true;
		try
		{
			this.errorsPara.setInnerHTML("");
			if(this.changePassCheckBox.getChecked())
			{	//update password
				passUpdatSucceed = this.updatePassword();

			}
			if(passUpdatSucceed)
			{	//update personal details
				this.updatePersonalDetails();
			}
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, this.errorsPara);
		}
	}//End of htmlButtonHandler

	/**
	 * Check date correctness.
	 *
	 * @param day the day
	 * @param month the month
	 *
	 * @return true, if date is correct
	 */
	private boolean checkDateCorrectness(final String day,final String month)
	{
		try
		{
			if(month.equals("2") && Integer.parseInt(day)> 28)
			{
				return false;
			}
			if(((month.equals("11")) || (month.equals("6"))|| (month.equals("4"))|| (month.equals("9"))) && Integer.parseInt(day)> 30)
			{
				return false;
			}
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, null);
		}
		return true;
	}//End of checkDateCorrectnesss

	/**
	 * Creates change password check box for the user to decide if he want to change is password.
	 * Creates correspond onClick change Password Box Handler
	 * Creates the birthday select. Include the birthday check box
	 * Creates correspond onClick birthday handler
	 * Initialize the dates
	 */
	private void createSelectAndCheckBox()
	{
		try
		{
			this.birthDay = new HtmlSelect(this,"birthDay");
			this.birthMonth = new HtmlSelect(this,"birthMonth");
			this.birthYear = new HtmlSelect(this,"birthYear");
			this.setSelected(true);
			this.birthDayCheckBox = new HtmlInputCheckbox(this, "dateBirth"){
				@Override protected void onClick(){
					EditProfilePage.this.checkBoxBirthdayHandler();
				}
			};
			this.changePassCheckBox = new HtmlInputCheckbox(this, "changePass"){
				@Override protected void onClick(){
					EditProfilePage.this.changePassBoxHandler();
				}
			};
		}
		catch(Exception e)
		{
			this.navigateToErrorPage(e, null);
		}
		try
		{
			this.birthDayCheckBox.setEnabled(true);
			this.changePassCheckBox.setEnabled(true);
			//Init days
			for(int i=1; i<=31;i++){
				this.birthDay.insertOption(i, Integer.toString(i));
			}
			//Init months
			for(int i=1; i<=12;i++){
				this.birthMonth.insertOption(i, Integer.toString(i));
			}
			//Init years
			int j = 1;
			for(int i=2009; i>=1950;i--){
				this.birthYear.insertOption(j, Integer.toString(i));
				j++;
			}
		}
		catch(Exception e)
		{
			this.navigateToErrorPage("Error in date component", null);
		}
	}//End of createSelectAndCheckBox

	/**
	 * Initialize the html form fields.
	 */
	private void initHtmlComponent()
	{
		try
		{
			this.newPass = new HtmlInputPassword(this,"newPass");
			this.pass = new HtmlInputPassword(this,"pass");
			this.passVerify = new HtmlInputPassword(this,"passVerify");
			this.firstName = new HtmlInputText(this,"firstName");
			this.lastName = new HtmlInputText(this,"lastName");
			this.residence = new HtmlInputText(this,"residence");
			this.femaleGender = new HtmlInputRadio(this,"femaleGender");
			this.maleGender = new HtmlInputRadio(this,"maleGender");
		}
		catch(Exception e)
		{
			this.navigateToErrorPage(e, null);
		}
	}

	/**
	 * Create save changes button.
	 * Create correspond override onClick method
	 */
	private void makeButton(){
		try
		{
			new HtmlButton(this,"saveChange"){
		        @Override protected void onClick(){
		        	EditProfilePage.this.htmlButtonHandler();
		        }
		    };
		}
		catch(Exception e)
		{
			this.navigateToErrorPage(e, null);
		}
	}

	/**
	 * Make the current page wait for 2 second for user to see the message on screen.
	 */
	private void pageWait()
	{
		try
		{
			Thread.sleep(2000);
		}
		catch (InterruptedException e)
		{
			//interrupt the page before 2000 mili is ok
		}
		catch(Exception e)
		{
			this.navigateToErrorPage(e, null);
		}
	}//End of pageWait

	/**
	 * Sets the errors paragraph with initialize empty text.
	 */
	private void setErrors()
	{
		try
		{
			this.errorsPara = new HtmlPara(this,"parError");
			this.errorsPara.setInnerHTML("");
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, this.errorsPara);
		}

	}

	/**
	 * Sets the passwords fields. to be enabled or disabled
	 *
	 * @param par the new passwords fields
	 */
	private void setPasswordsFields(final boolean par)
	{
		try
		{
			this.pass.setDisabled(par);
			this.newPass.setDisabled(par);
			this.passVerify.setDisabled(par);
		}
		catch (Exception e)
		{
			this.navigateToErrorPage("Error in forms components", null);
		}
	}


	/**
	 * Sets the birthday selected to be enabled or disabled.
	 *
	 * @param par the new selected
	 */
	private void setSelected(final boolean par)
	{
		try
		{
			this.birthDay.setDisabled(par);
			this.birthMonth.setDisabled(par);
			this.birthYear.setDisabled(par);
		}
		catch (Exception e)
		{
			this.navigateToErrorPage("Error in date components", null);
		}
	}


	/**
	 * Update password.
	 * Reading password from html page updates password if necessary.
	 * Dealing with all correspond exceptions
	 * @return true, if successful
	 */
	private boolean updatePassword()
	{
		try
		{
			String oldPassword = this.pass.getValue();
			String newPassword = this.newPass.getValue();
			String verifyPassword = this.passVerify.getValue();
			if((newPassword.equals(""))||(oldPassword.equals("")) ||(verifyPassword.equals("")))
			{
				this.errorsPara.setInnerHTML("Missing password");
				this.newPass.setValue("");
				this.pass.setValue("");
				this.passVerify.setValue("");
				return false;
			}
			else
			{	//checks if password and verify pass is match
				if(newPassword.equals(verifyPassword))
				{
					long userId = this.getUser().getId();
					this.getForumLogic().updatePassword(userId,oldPassword,newPassword);
					Log.getLogger(Subsystem.PRESENTATION_MODEL).finest("user " + userId + " changed his password");
					return true;
				}
				else
				{
					this.errorsPara.setInnerHTML("Password verification doesn't match, Please type again.");
					this.pass.setValue("");
					this.newPass.setValue("");
					this.passVerify.setValue("");
					return false;
				}
			}
		}
		catch(NotFoundException e)
		{
			try
			{
				this.errorsPara.setInnerHTML("Username doesn't exist ");
				Log.getLogger(Subsystem.PRESENTATION_MODEL).info("unpermitted action. username not exist") ;
			}
			catch (Jaxception e1)
			{
				this.navigateToErrorPage(e1, this.errorsPara);
			}
			return false;
		}
		catch(BadPasswordException e)
		{
			try
			{
				this.errorsPara.setInnerHTML("Wrong Password!");
				this.pass.setValue("");
				this.newPass.setValue("");
				this.passVerify.setValue("");
			}
			catch (Jaxception e1)
			{
				this.navigateToErrorPage(e1, null);
			}
			return false;
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, null);
			return false;
		}
	}

	/**
	 * Update personal details.
	 * Reading all personal details from html page updates if necessary.
	 * Dealing with all correspond exceptions
	 */
	private void updatePersonalDetails()
	{
		try
		{
			String newFirstName = this.firstName.getValue();
			String newLastName = this.lastName.getValue();
			String newResidence = this.residence.getValue();
			String gender = "";
			String dateOfBirth = "";
			if(this.femaleGender.getChecked())
			{
				gender = "Female";
			}
			else if(this.maleGender.getChecked())
			{
				gender="Male";
			}
			if(this.birthDayCheckBox.getChecked()){
				String day = this.birthDay.getOption(this.birthDay.getSelectedIndex()).getValue();
				String month = this.birthMonth.getOption(this.birthMonth.getSelectedIndex()).getValue();
				String year = this.birthYear.getOption(this.birthYear.getSelectedIndex()).getValue();
				if(!this.checkDateCorrectness(day,month))
				{
					this.errorsPara.setInnerHTML("Invalid date, correct and update again");
					return;
				}
				dateOfBirth = day+"/"+month+"/"+year;
			}
			if(!this.birthDayCheckBox.getChecked()&& !this.changePassCheckBox.getChecked() && newFirstName.equals("") &&
				newLastName.equals("") && newResidence.equals("") && gender.equals(""))
			{
				this.errorsPara.setInnerHTML("Please insert any parameter to update profile");
				return;
			}
			long userId = this.getUser().getId();
			this.getForumLogic().updateMemberDetails(userId,newFirstName,newLastName,dateOfBirth,gender
				,newResidence);
			Log.getLogger(Subsystem.PRESENTATION_MODEL).finest("user " + userId + " has changed his profile details");
			this.errorsPara.setStyle("color", "blue");
			this.errorsPara.setInnerHTML("Update Profile successful");
			this.pageWait();
			this.navigateToPage(MainPage.HOME_PAGE) ;
		}
		catch(NotFoundException e)
		{
			try
			{
				this.errorsPara.setInnerHTML("Username doesn't exist ");
				Log.getLogger(Subsystem.PRESENTATION_MODEL).info("unpermitted action. username not exist") ;
			}
			catch (Jaxception e1)
			{
				this.navigateToErrorPage(e1, this.errorsPara);
			}
		}
		catch (UnpermittedActionException e)
		{
			this.navigateToErrorPage(e, null);
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, null);
		}
	}
	
	/* (non-Javadoc)
	 * @see presentation.web.MainPage#onLoad()
	 */
	/**
	 * Initialize member details in the fields 
	 */
	@Override
	protected void onLoad()
	{
		super.onLoad();
		try
		{
			UIMember currMember = (UIMember)getUser();
			this.firstName.setValue(currMember.getFirstName());
			this.lastName.setValue(currMember.getLastName());
			this.residence.setValue(currMember.getResidence());
			String dob = currMember.getDateOfBirth();
			if (!dob.equals(""))
			{
				String[] dobArr = dob.split("/");
				this.birthDay.setSelectedIndex(Integer.parseInt(dobArr[0])-1);
				this.birthMonth.setSelectedIndex(Integer.parseInt(dobArr[1])-1);
				this.birthYear.setSelectedIndex(2009 - Integer.parseInt(dobArr[2]));
			}
			else
			{
				this.birthDay.setSelectedIndex(0);
				this.birthMonth.setSelectedIndex(0);
				this.birthYear.setSelectedIndex(0);
			}
			String gender = currMember.getGender();
			if (gender.equals("Male"))
			{
				this.maleGender.setChecked(true);
			}
			else
			{
				if (gender.equals("Female"))
				{
					this.femaleGender.setChecked(true);
				}
			}
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, null);
		}
		
	}
}
